package cn.iocoder.yudao.module.resource.service.session.impl;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.resource.api.enums.EnumAipError;
import cn.iocoder.yudao.module.resource.controller.admin.session.vo.SessionPageReqVO;
import cn.iocoder.yudao.module.resource.controller.admin.session.vo.SessionSaveReqVO;
import cn.iocoder.yudao.module.resource.dal.dataobject.session.SessionDO;
import cn.iocoder.yudao.module.resource.dal.mysql.session.SessionMapper;
import cn.iocoder.yudao.module.resource.dal.redis.ResourceLockRedisDAO;
import cn.iocoder.yudao.module.resource.service.session.SessionService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;

/**
 * 会话 Service 实现类
 *
 * @author lizhongwen
 */
@Service
@Validated
public class SessionServiceImpl implements SessionService {

    @Resource
    private SessionMapper sessionMapper;
    @Resource
    private ResourceLockRedisDAO lockRedisDAO;

    @Override
    public Long createSession(SessionSaveReqVO createReqVO) {
        // 插入
        SessionDO session = BeanUtils.toBean(createReqVO, SessionDO.class);
        sessionMapper.insert(session);
        // 返回
        return session.getSessionId();
    }

    @Override
    public void updateSession(Long sessionId, SessionSaveReqVO updateReqVO) {
        // 校验存在
        validateSessionExists(sessionId);
        // 更新
        SessionDO updateObj = BeanUtils.toBean(updateReqVO, SessionDO.class);
        sessionMapper.updateById(updateObj);
    }

    @Override
    public void deleteSession(Long id) {
        // 校验存在
        validateSessionExists(id);
        // 删除
        sessionMapper.deleteById(id);
    }

    @Override
    public void deleteSessionByUserId(Long userId, Long id) {
        sessionMapper.deleteSessionByUserId(userId, id);
    }

    private void validateSessionExists(Long id) {
        if (sessionMapper.selectById(id) == null) {
            throw exception(EnumAipError.SESSION_NOT_EXISTS);
        }
    }

    @Override
    public SessionDO getSession(Long id) {
        return sessionMapper.selectById(id);
    }

    @Override
    public SessionDO getSessionByUserId(Long userId, Long sessionId) {
        return sessionMapper.selectOne(SessionDO::getCreator, userId, SessionDO::getSessionId, sessionId);
    }

    @Override
    public Long getSessionByRoleIdWithLock(Long loginUserId, Long roleId, Integer storyId) {
        final Long sessionId = lockRedisDAO.lockUserRole(loginUserId, roleId, storyId, () -> {
            final SessionDO session = getSessionByRoleId(loginUserId, roleId, storyId);
            if (session == null) {
                return createSession(loginUserId, roleId, storyId);
            } else {
                return session.getSessionId();
            }
        });
        return sessionId;
    }

    private Long createSession(Long loginUserId, Long roleId, Integer storyId) {
        // 插入
        SessionDO session = new SessionDO();
        session.setCreator(loginUserId.toString());
        session.setRoleId(roleId);
        session.setStoryId(storyId);
        sessionMapper.insert(session);
        // 返回
        return session.getSessionId();
    }

    @Override
    public SessionDO getSessionByRoleId(Long userId, Long roleId, Integer storyId) {
        if (storyId != null) {
            return sessionMapper.selectOne(SessionDO::getCreator, userId, SessionDO::getRoleId, roleId, SessionDO::getStoryId, storyId);
        } else {
            return sessionMapper.selectOne(SessionDO::getCreator, userId, SessionDO::getRoleId, roleId);
        }
    }

    @Override
    public PageResult<SessionDO> getSessionPage(SessionPageReqVO pageReqVO) {
        return sessionMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<SessionDO> selectPageByUserId(Long userId, SessionPageReqVO pageReqVO) {
        return sessionMapper.selectPageByUserId(userId, pageReqVO);
    }
}